package controller;

import entity.Comune;
import java.io.BufferedInputStream;
import java.io.BufferedReader;
import java.io.DataInputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.UnsupportedEncodingException;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.logging.Level;
import java.util.logging.Logger;
import java.util.zip.ZipInputStream;
import javax.ejb.EJB;
import javax.ejb.Stateless;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import javax.persistence.Query;
import sbForEntityClasses.ComuneFacadeLocal;
import utilities.QueryBuilder;

/**
 * Metodi per la gestione dei dati dei comuni italiani
 * @author lxn
 */
@Stateless
public class ControllerComuni implements ControllerComuniLocal {

    @EJB
    private ComuneFacadeLocal comuneFacade;
    
    @PersistenceContext(unitName = "ShippingShareBisBis-ejbPU")
    private EntityManager em;
    
    private final String URL_LISTA_COMUNI = "http://lab.comuni-italiani.it/files/listacomuni.zip";

    /**
     * Inizializza nel database la lista dei comuni
     */
    @Override
    public void creaComuni() {
        if (comuneFacade.count()==0){
            updateListaComuni();
        }
    }

    enum Region {

        ABR("Abruzzo"),
        BAS("Basilicata"),
        CAL("Calabria"),
        CAM("Campania"),
        EMR("Emilia-Romagna"),
        FVG("Friuli Venezia Giulia"),
        LAZ("Lazio"),
        LIG("Liguria"),
        LOM("Lombardia"),
        MAR("Marche"),
        MOL("Molise"),
        PIE("Piemonte"),
        PUG("Puglia"),
        SAR("Sardegna"),
        SIC("Sicilia"),
        TAA("Trentino-Alto Adige"),
        TOS("Toscana"),
        UMB("Umbria"),
        VDA("Valle d'Aosta"),
        VEN("Veneto");
        
        private final String name;

        Region(String name) {
            this.name = name;
        }

        String getName() {
            return name;
        }
        
    }

    /**
     * Restituisce la regione in cui si trova il comune in input
     * @param municipality il comune in input
     * @return la regione in cui si trova il comune, se riconosciuto; la stringa vuota, altrimenti
     */
    @Override
    public String getRegion(String municipality) {
        QueryBuilder qb = new QueryBuilder("Comune", em);

        qb.addWhereEqClause("name", municipality);

        Query q = qb.getQueryObject();

        try{
            return ((Comune) q.getSingleResult()).getRegion();
        } catch (Exception e){
            return "";
        }
    }

    /**
     * Aggiorna la lista dei comuni nel database, in caso cambiassero
     */
    @Override
    public void updateListaComuni() {
        BufferedReader br = null;
        Comune c;
        DataInputStream dis;
        String line;
        String[] tokens;
        URL u = null;
        ZipInputStream zis = null;

        try {
            u = new URL(URL_LISTA_COMUNI);
        } catch (MalformedURLException ex) {
            Logger.getLogger(ControllerComuni.class.getName()).log(Level.SEVERE, null, ex);
        }

        try {
            zis = new ZipInputStream(new BufferedInputStream(u.openStream()));
        } catch (IOException ex) {
            Logger.getLogger(ControllerComuni.class.getName()).log(Level.SEVERE, null, ex);
        }

        dis = new DataInputStream(zis);

        try {
            br = new BufferedReader(new InputStreamReader(dis, "ISO-8859-1"));
        } catch (UnsupportedEncodingException ex) {
            Logger.getLogger(ControllerComuni.class.getName()).log(Level.SEVERE, null, ex);
        }

        try {
            zis.getNextEntry();
            br.readLine(); // Salto la prima riga.
            while ((line = br.readLine()) != null) {
                tokens = line.split(";");
                c = new Comune(tokens[1], Region.valueOf(tokens[3]).getName());
                comuneFacade.create(c);
            }
            br.close();
        } catch (IOException ex) {
            Logger.getLogger(ControllerComuni.class.getName()).log(Level.SEVERE, null, ex);
        }
    }

    /**
     * Persistenza
     * @param object
     */
    public void persist(Object object) {
        em.persist(object);
    }

}
